//
// Created by ftd on 2021/8/18.
//

#include "utils/ring_buffer.h"
#include <algorithm>
#include <string.h>

enum {
    //环形缓冲初始大小100M
    kRingBufferInitLen = 1048576,
};

RingBuffer::RingBuffer()
        : in_(0), out_(0), buffer_size_(kRingBufferInitLen), buffer(new uint8_t[kRingBufferInitLen]) {

}

RingBuffer::~RingBuffer() {

}

uint8_t* RingBuffer::NewBuffer() {
    try {
        std::unique_ptr<uint8_t[]> new_buffer(new uint8_t[buffer_size_ * 2]);
        uint32_t l = std::min(in_ - out_, buffer_size_ - (out_ & (buffer_size_ - 1)));

        memcpy(new_buffer.get(), buffer.get() + (out_ & (buffer_size_ - 1)), l);
        memcpy(new_buffer.get() + l, buffer.get(), in_ - out_ - l);
        buffer = std::move(new_buffer);
        buffer_size_ *= 2;
        in_ -= out_;
        out_ = 0;
    }
    catch (const std::exception &e) {
        fprintf(stderr, "%s:new buffer_size_:%ld buffer fail %s\n", __FUNCTION__, buffer_size_, e.what());
        return nullptr;
    }
    return buffer.get() + in_;
}

bool RingBuffer::PutData(const void* in_buffer, int len) {
    if (buffer_size_ - in_ + out_ < len) {
        NewBuffer();
    }
    auto l = std::min((int64_t)len, buffer_size_ - (in_ & (buffer_size_ - 1)));
    memcpy(buffer.get() + (in_ & (buffer_size_ - 1)), in_buffer, l);
    memcpy(buffer.get(), (uint8_t*)in_buffer + l, len - l);
    in_ += len;
    return true;
}


bool RingBuffer::GetData(void* out_buffer, int len) {
    if (len > in_ - out_) {
        return false;
    }
    auto l = std::min((int64_t)len, buffer_size_ - (out_ & (buffer_size_ - 1)));
    memcpy(out_buffer, buffer.get() + (out_ & (buffer_size_ - 1)), l);
    memcpy((uint8_t*)out_buffer + l, buffer.get(), len - l);
    out_ += len;
    return true;
}